package com.bookstore.controller;

import com.bookstore.dto.ApiResponse;
import com.bookstore.service.BaseService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 通用控制器类，处理基本的CRUD操作
 * @param <T> 实体类型
 * @param <D> DTO类型
 * @param <ID> ID类型
 */
public abstract class BaseController<T, D, ID> {
    
    protected final BaseService<T, D, ID> service;
    
    public BaseController(BaseService<T, D, ID> service) {
        this.service = service;
    }
    
    /**
     * 获取所有实体
     * @return 实体DTO列表
     */
    @GetMapping
    public ResponseEntity<ApiResponse<List<D>>> findAll() {
        try {
            List<D> entities = service.findAll();
            return ResponseEntity.ok(ApiResponse.success(entities));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(ApiResponse.error("获取数据失败：" + e.getMessage()));
        }
    }
    
    /**
     * 分页获取实体
     * @param page 页码
     * @param size 每页大小
     * @param sort 排序字段
     * @param direction 排序方向
     * @return 分页结果
     */
    @GetMapping("/page")
    public ResponseEntity<ApiResponse<Page<D>>> findAll(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String sort,
            @RequestParam(defaultValue = "ASC") String direction) {
        try {
            Pageable pageable;
            if (sort != null && !sort.isEmpty()) {
                Sort.Direction dir = "DESC".equalsIgnoreCase(direction) ? Sort.Direction.DESC : Sort.Direction.ASC;
                pageable = PageRequest.of(page, size, Sort.by(dir, sort));
            } else {
                pageable = PageRequest.of(page, size);
            }
            Page<D> entities = service.findAll(pageable);
            return ResponseEntity.ok(ApiResponse.success(entities));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(ApiResponse.error("获取数据失败：" + e.getMessage()));
        }
    }
    
    /**
     * 根据ID获取实体
     * @param id 实体ID
     * @return 实体DTO
     */
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<D>> findById(@PathVariable ID id) {
        try {
            D entity = service.findById(id);
            return ResponseEntity.ok(ApiResponse.success(entity));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(ApiResponse.error("获取数据失败：" + e.getMessage()));
        }
    }
    
    /**
     * 保存实体
     * @param dto 实体DTO
     * @return 保存后的实体DTO
     */
    @PostMapping
    public ResponseEntity<ApiResponse<D>> save(@RequestBody D dto) {
        try {
            D savedEntity = service.save(dto);
            return ResponseEntity.ok(ApiResponse.success("添加成功", savedEntity));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(ApiResponse.error("添加失败：" + e.getMessage()));
        }
    }
    
    /**
     * 更新实体
     * @param id 实体ID
     * @param dto 实体DTO
     * @return 更新后的实体DTO
     */
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<D>> update(@PathVariable ID id, @RequestBody D dto) {
        try {
            D updatedEntity = service.update(id, dto);
            return ResponseEntity.ok(ApiResponse.success("更新成功", updatedEntity));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(ApiResponse.error("更新失败：" + e.getMessage()));
        }
    }
    
    /**
     * 删除实体
     * @param id 实体ID
     * @return 操作结果
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponse<Void>> delete(@PathVariable ID id) {
        try {
            service.delete(id);
            return ResponseEntity.ok(ApiResponse.success("删除成功", null));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(ApiResponse.error("删除失败：" + e.getMessage()));
        }
    }
}